import EMinderNavbar from './Navbar'
import EMinderHotbox from './Hotbox'
import EMinderTips from './Tips'

export default {
  name: 'e-minder',
  components: { EMinderNavbar, EMinderHotbox, EMinderTips },
  props: {
    data: {
      type: Object,
      default: null
    },
    editable: {
      type: Boolean,
      default: true
    },
    readonly: {
      type: Boolean,
      default: false
    },
    menus: {
      type: Array,
      default: null
    },
    height: {
      type: Number,
      default: 0
    },
    autoHeight: {
      type: Boolean,
      default: false
    },
    showNavbar: {
      type: Boolean,
      default: true
    },
    showTips: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    style() {
      let height = this.height
      if (this.autoHeight) {
        height = this.fullHeight - height
      }
      return { height: `${height}px` }
    }
  },
  watch: {
    data: function() {
      this.importJson()
    }
  },
  mounted() {
    const el = this.$refs.minder
    // eslint-disable-next-line no-undef
    this.minder = new kityminder.Minder({
      x: 200,
      renderTo: el
    })
    this.importJson()
    this.$emit('init-success', this.minder)

    // 注册事件
    this.registryEvent()
  },
  data() {
    return {
      minder: null,
      sourceNode: Object,
      fullHeight: document.body.clientHeight
    }
  },
  render(h) {
    const children = []
    if (this.showNavbar) {
      children.push(h(EMinderNavbar, {
        props: {
          minder: this.minder
        }
      }))
    }

    if (this.menus && !this.readonly) {
      children.push(h(EMinderHotbox, {
        ref: 'hotbox',
        props: {
          minder: this.minder,
          menus: this.menus,
          editable: this.editable
        }
      }))
    }

    if (this.editable && this.showTips) {
      children.push(h(EMinderTips))
    }

    // navbar
    return h('div', {
      class: {
        'container': true
      },
      style: this.style
    }, [
      h('div', {
        ref: 'minder',
        class: { 'e-minder-editor': true },
        style: { 'height': '100%' }
      }),
      h('div', {}, children)
    ])
  },
  methods: {
    importJson() {
      if (this.data) {
        this.minder.importJson({
          theme: 'fmea-blue',
          template: 'fmea',
          root: this.data
        })

        this.$emit('load-minder-success')
      }
    },
    registryEvent() {
      // 页面size变更
      window.onresize = () => {
        // 避免页面操作卡顿，增加timeout
        setTimeout(() => {
          this.fullHeight = document.body.clientHeight
          if (this.minder) {
            this.minder.execCommand('camera', this.minder.getRoot())
          }
        }, 200)
      }

      // 节点展开事件
      this.minder.on('expandNodeEvent', (res) => {
        this.$emit('expand-node-event', res.currentNode == null ? this.minder.getSelectedNode() : res.currentNode)
      })

      // 脑图自定义事件
      this.registryCustomerEvent(e => {
        // 传递事件至hotbox
        if (undefined !== this.menus) {
          this.$refs.hotbox.dispatch(e)
        }

        // 复制粘贴事件
        if (e.type.toLowerCase() === 'keydown') {
          if (e.ctrlKey) {
            if (e.keyCode === 67) {
              if (this.minder.getSelectedNode()) {
                this.sourceNode = this.minder.getSelectedNode()
              }
            }
            if (e.keyCode === 86) {
              if (this.minder.getSelectedNode()) {
                const targetNode = this.minder.getSelectedNode()
                this.$emit('paste-node-event', this.sourceNode, targetNode)
              }
            }
          }
        }
      })
    },
    registryCustomerEvent(event) {
      const FOCUS_CLASS = 'hotbox-focus'
      const RECEIVER_CLASS = 'hotbox-key-receiver'

      let _receiver
      let _actived = true
      let _receiverIsSelfCreated = false
      const $container = this.$refs.minder

      _createReceiver()
      _bindReceiver()
      _bindContainer()
      _active()

      function _createReceiver() {
        _receiver = document.createElement('input')
        _receiver.classList.add(RECEIVER_CLASS)
        $container.appendChild(_receiver)
        _receiverIsSelfCreated = true
      }

      function _bindReceiver() {
        _receiver.onkeyup = _handle
        _receiver.onkeypress = _handle
        _receiver.onkeydown = _handle
        _receiver.onfocus = _active
        _receiver.onblur = _deactive
        if (_receiverIsSelfCreated) {
          _receiver.oninput = function(e) { _receiver.value = null }
        }
      }

      function _bindContainer() {
        $container.onmousedown = function(e) {
          _active()
          e.preventDefault()
        }
      }

      function _handle(keyEvent) {
        if (!_actived) return
        event(keyEvent)
      }

      function _active() {
        _receiver.select()
        _receiver.focus()
        _actived = true
        $container.classList.add(FOCUS_CLASS)
      }

      function _deactive() {
        _receiver.blur()
        _actived = false
        $container.classList.remove(FOCUS_CLASS)
      }

      this.handle = _handle
      this.active = _active
      this.deactive = _deactive
    },
    // 添加脑图节点
    appendChildNode(data) {
      const selected = this.minder.getSelectedNode()
      if (selected.data.expandState === 'collapse' && selected.children.length === 0) {
        this.minder.fire('expandNodeEvent')
        this.minder.getSelectedNode().setData('expandState', 'expand')
      } else {
        if (selected.children.length === 0) {
          this.minder.getSelectedNode().setData('expandState', 'expand')
        }
        this.minder.execCommand('AppendChildNode', data)
      }

      // 如果是接口下添加节点，双向添加
      if (selected.isInterfaceChildNode()) {
        this.minder.getAllNode().forEach(node => {
          if (selected.getData('extraId') === node.getData('extraId') && selected.getData('nodeType') === node.getData('nodeType') && selected.getData('id') !== node.getData('id')) {
            this.minder.execCommand('AppendChildNode', data, node)
          }
        })
      }
    },
    // 添加脑图节点（深度）
    appendChildNodeDeep(childNode, parentNode) {
      const result = this.minder.execCommand('AppendChildNode', childNode.data, parentNode)
      for (let i = 0; i < childNode.children.length; i++) {
        this.appendChildNodeDeep(childNode.children[i], result)
      }
      return result
    }
  },
  destroyed() {
    window.onresize = null
  }
}
